#include <head.h>

#define SIZE_BUF_MAX 1024

typedef struct file_str
{
    int src_fd;
    int desk_fd;
    off_t start;
    off_t end;
} file_str;

// 拷贝函数
void * copy_file(void * str)
{
    
    file_str *file_str_func = (file_str *)str;
    int src_fd = file_str_func->src_fd;
    int desk_fd = file_str_func->desk_fd;
    off_t start = file_str_func->start;
    off_t end = file_str_func->end;
    // 设定缓冲区
    char buf[SIZE_BUF_MAX];
    // 设定文件起始位置
    lseek(src_fd, start, SEEK_SET);
    lseek(desk_fd, start, SEEK_SET);

    // 开始拷贝
    size_t byte_read = 0;
    size_t byte_write = 0;

    while (start < end)
    {
        if ((byte_read = read(src_fd, buf, SIZE_BUF_MAX)) <= 0)
        {
            break;
        }
        if ((byte_write = write(desk_fd, buf, byte_read)) <= 0)
        {
            break;
        }

        // 位置迭代
        start += byte_write;
    }
    printf("拷贝成功\n");
    return NULL;
}

int main(int argc, char const *argv[])
{
    // 安全判定
    if (4 != argc)
    {
        printf("格式错误 %s dest src\n", argv[0]);
        return 0;
    }

    int pthread_num = atoi(argv[3]);

    // 打开文件
    int desk_fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0664); // 目标文件
    OPEN_ERR(desk_fd);

    int src_fd = open(argv[2], O_RDONLY); // 源文件
    OPEN_ERR(src_fd);



    // 获取文件状态
    struct stat file_stat; // 文件状态结构体

    if (fstat(src_fd, &file_stat) < 0)
    {
        perror("fstat err");
        close(desk_fd);
        close(src_fd);
        return 0;
    }

    // 获取文件大小 并计算每个进程 所拷贝的范围
    off_t file_size = file_stat.st_size; // 文件大小
    off_t part_size = file_size / pthread_num;

    // 线程的tid
    pthread_t tid[pthread_num];

    // 设定结构体
    file_str file_str_arr[pthread_num];

    // 创建进程
    for (int i = 0; i < pthread_num; i++)
    {
        
        // 计算位置
        off_t start = i * part_size; // 记录开始位置
        off_t end = (i == pthread_num - 1) ? file_size : part_size + start;

        // 结构体写入数据
        file_str_arr[i].desk_fd = desk_fd;
        file_str_arr[i].src_fd = src_fd;
        file_str_arr[i].end = end;
        file_str_arr[i].start = start;

        // 创建多线程
        if (0 != pthread_create(&tid[i], NULL, copy_file, (void *)&file_str_arr[i]))
        {
            perror("pthread_create error:");
            close(desk_fd);
            close(src_fd);
            exit(1);
        }

        // 设定分离态
        pthread_detach( tid[i] );
    }

    

    // 主进程 回收资源
    // pthread_join(tid[1] , NULL);
    // pthread_join(tid[0] , NULL);

    sleep(5);
    


    // 关闭文件
    close(src_fd);
    close(desk_fd);

    return 0;
}
